import { PointerEventTypes, PointerInfo } from '@babylonjs/core/Events/pointerEvents';
import { Scene } from '@babylonjs/core/scene';
import { CreateHandleTo, ICallback, IHandle, RemoveHandle } from '../data/data-handle';


/**
 * 用户操作捕获
 */
class UserGestureCapture {

    private static _counter: number = 0;
    private static _scene: Scene | undefined | null;
    private static _debutHandles: IHandle<void>[] = [];
    private static _actionHandles: IHandle<boolean>[] = [];

    /**
     * 用户操作次数
     */
    public static get count(): number {
        return this._counter;
    }

    /**
     * 有效用户操作的类型（默认只有pointerDown事件）
     */
    public static readonly types: PointerEventTypes[] = [PointerEventTypes.POINTERUP];

    /**
     * 设置事件场景
     * @param scene 事件场景
     */
    public static setScene(scene: Scene): void {
        this.bindEvent(scene);
    }

    /**
     * 添加首次用户操作时的回调函数
     * @param callback 回调函数 
     * @returns 回调函数对象
     */
    public static onDebut(callback: ICallback<void>): IHandle<void> {
        return CreateHandleTo(callback, this._debutHandles);
    }

    /**
     * 移除首次用户操作时的回调函数
     * @param handle 回调函数对象
     */
    public static removeDebutHandle(handle: number | IHandle<void>): void {
        RemoveHandle(handle, this._debutHandles);
    }

    /**
     * 添加用户操作时的回调函数
     * @param callback 回调函数
     * @returns 回调函数对象
     */
    public static onAction(callback: ICallback<boolean>): IHandle<boolean> {
        return CreateHandleTo(callback, this._actionHandles);
    }

    /**
     * 移除用户操作时的回调函数
     * @param handle 回调函数对象
     */
    public static removeActionHandle(handle: number | IHandle<boolean>): void {
        RemoveHandle(handle, this._actionHandles);
    }

    /**
     * 重设用户操作次数
     */
    public static reset(): void {
        this._counter = 0;
    }

    private static bindEvent(scene?: Scene | null): void {
        if (!scene) {
            if (this._scene) this._scene.onPointerObservable.removeCallback(this.gestureHandle);
            this._scene = scene;
            return;
        }
        if (this._scene) {
            if (this._scene.uid === scene.uid) return;
            this._scene.onPointerObservable.removeCallback(this.gestureHandle);
        }

        this._scene = scene;
        this._scene.onPointerObservable.add(this.gestureHandle);
    }

    private static gestureHandle(e: PointerInfo): void {
        if (!UserGestureCapture.types.includes(e.type)) return;

        UserGestureCapture._counter++;
        const isDebut = UserGestureCapture._counter < 2;
        if (isDebut) {
            UserGestureCapture._debutHandles.forEach(handle => handle.callback());
        }
        UserGestureCapture._actionHandles.forEach(handle => handle.callback(isDebut));
    }

}


export { UserGestureCapture };